﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Xml.Serialization;
using System.IO;

namespace ImPM.Application
{
    public static class ImPMPerformanceCounterFactory
    {
        // Fields
        private static string CategoryHelp = "ImPM Performance Counters";
        private static string CategoryHelpMultipleInstance = "ImPM Multiple Instance Performance Counters";
        private static string CategoryName = "CRM ";
        private static string CategoryNameMultipleInstance = "CRM Multi Instance ";
        private static CounterContainer counterContainer;
        private static Dictionary<KeyValuePair<string, string>, ImPMPerformanceCounter> countersMultipleInstance = new Dictionary<KeyValuePair<string, string>, ImPMPerformanceCounter>();
        private static Dictionary<string, ImPMPerformanceCounter> countersSingleInstance = new Dictionary<string, ImPMPerformanceCounter>();

        // Methods
        public static bool CreateInstance(string counterName, string instanceName, string component)
        {
            foreach (KeyValuePair<string, string> pair in countersMultipleInstance.Keys)
            {
                if (pair.Key.Equals(counterName))
                {
                    PerformanceCounter pc = new PerformanceCounter(CategoryNameMultipleInstance + component, counterName, instanceName, false);
                    pc.RawValue = 0L;
                    KeyValuePair<string, string> key = new KeyValuePair<string, string>(counterName, instanceName);
                    try
                    {
                        countersMultipleInstance.Add(key, new ImPMPerformanceCounter(pc));
                    }
                    catch (ArgumentException)
                    {
                    }
                    return true;
                }
            }
            return false;
        }

        public static void DecrementCounter(string counterName)
        {
            DecrementCounter(counterName, (long)1L);
        }

        public static void DecrementCounter(string counterName, long value)
        {
            ImPMPerformanceCounter counter;
            countersSingleInstance.TryGetValue(counterName, out counter);
            if (counter == null)
            {
                throw new ImPMException(string.Format(CultureInfo.InvariantCulture, "Cannot find Counter: {0}", new object[] { counterName }), -2147220970);
            }
            counter.DecrementBy(value);
        }

        public static void DecrementCounter(string counterName, string instanceName)
        {
            DecrementCounter(counterName, instanceName, 1L);
        }

        public static void DecrementCounter(string counterName, string instanceName, long value)
        {
            ImPMPerformanceCounter counter;
            KeyValuePair<string, string> key = new KeyValuePair<string, string>(counterName, instanceName);
            countersMultipleInstance.TryGetValue(key, out counter);
            if (counter == null)
            {
                throw new ImPMException(string.Format(CultureInfo.InvariantCulture, "Cannot find Counter: {0} and Instance {1}", new object[] { counterName, instanceName }), -2147220970);
            }
            counter.DecrementBy(value);
        }

        public static bool Exists(string counterName)
        {
            if (countersSingleInstance.ContainsKey(counterName))
            {
                return true;
            }
            foreach (KeyValuePair<string, string> pair in countersMultipleInstance.Keys)
            {
                if (pair.Key.Equals(counterName))
                {
                    return true;
                }
            }
            return false;
        }

        public static ImPMPerformanceCounter GetCounter(string counterName)
        {
            ImPMPerformanceCounter counter;
            countersSingleInstance.TryGetValue(counterName, out counter);
            return counter;
        }

        public static ImPMPerformanceCounter GetCounter(string counterName, string instanceName)
        {
            ImPMPerformanceCounter counter;
            countersMultipleInstance.TryGetValue(new KeyValuePair<string, string>(counterName, instanceName), out counter);
            return counter;
        }

        public static void IncrementCounter(string counterName)
        {
            IncrementCounter(counterName, (long)1L);
        }

        public static void IncrementCounter(string counterName, long value)
        {
            ImPMPerformanceCounter counter;
            countersSingleInstance.TryGetValue(counterName, out counter);
            if (counter == null)
            {
                throw new ImPMException(string.Format(CultureInfo.InvariantCulture, "Cannot find Counter: {0}", new object[] { counterName }), -2147220970);
            }
            counter.IncrementBy(value);
        }

        public static void IncrementCounter(string counterName, string instanceName)
        {
            IncrementCounter(counterName, instanceName, 1L);
        }

        public static void IncrementCounter(string counterName, string instanceName, long value)
        {
            ImPMPerformanceCounter counter;
            KeyValuePair<string, string> key = new KeyValuePair<string, string>(counterName, instanceName);
            countersMultipleInstance.TryGetValue(key, out counter);
            if (counter == null)
            {
                throw new ImPMException(string.Format(CultureInfo.InvariantCulture, "Cannot find Counter: {0} and Instance {1}", new object[] { counterName, instanceName }), -2147220970);
            }
            counter.IncrementBy(value);
        }

        public static void LoadCounters(PerformanceCounterLoadSetting settings, string component)
        {
            using (EventLog log = new EventLog())
            {
                log.Source = "ImPMPerfCounters";
                using (ImPMEventLog log2 = new ImPMEventLog(log))
                {
                    try
                    {
                        using (Stream stream = typeof(ImPMPerformanceCounterFactory).Assembly.GetManifestResourceStream("ImPMPerformanceCounters"))
                        {
                            XmlSerializer serializer = new XmlSerializer(typeof(CounterContainer));
                            counterContainer = (CounterContainer)serializer.Deserialize(stream);
                        }
                        LoadCounters(counterContainer, settings, component);
                    }
                    catch (Exception)
                    {
                        log2.WriteEntry(EventLogEntryType.Error, 0xc0004324L, new object[] { component });
                        throw;
                    }
                    log2.WriteEntry(EventLogEntryType.Information, 0x4325L, new object[] { component });
                }
            }
        }

        public static void LoadCounters(CounterContainer counterContainer, PerformanceCounterLoadSetting settings, string component)
        {
            CounterCreationDataCollection counterData = new CounterCreationDataCollection();
            CounterCreationDataCollection datas2 = new CounterCreationDataCollection();
            List<string> list = new List<string>();
            List<string> list2 = new List<string>();
            Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
            if (counterContainer.Counters != null)
            {
                foreach (PerformanceCounterInfo info in counterContainer.Counters)
                {
                    if (info.Component.ToUpperInvariant().Equals(component.ToUpperInvariant()))
                    {
                        if (info.InstanceType.ToUpperInvariant().Equals("MULTIPLE"))
                        {
                            list2.Add(info.Name);
                            dictionary.Add(info.Name, new List<string>(info.InstanceName));
                            datas2.Add(new CounterCreationData(info.Name, info.CounterInfo, (PerformanceCounterType)Enum.Parse(typeof(PerformanceCounterType), info.CounterType)));
                        }
                        else
                        {
                            list.Add(info.Name);
                            counterData.Add(new CounterCreationData(info.Name, info.CounterInfo, (PerformanceCounterType)Enum.Parse(typeof(PerformanceCounterType), info.CounterType)));
                        }
                    }
                }
                if ((settings == PerformanceCounterLoadSetting.RegisterAndCreate) || (settings == PerformanceCounterLoadSetting.RegisterOnly))
                {
                    if (counterData.Count > 0)
                    {
                        if (PerformanceCounterCategory.Exists(CategoryName + component))
                        {
                            PerformanceCounterCategory.Delete(CategoryName + component);
                        }
                        PerformanceCounterCategory.Create(CategoryName + component, CategoryHelp, PerformanceCounterCategoryType.SingleInstance, counterData);
                    }
                    if (datas2.Count > 0)
                    {
                        if (PerformanceCounterCategory.Exists(CategoryNameMultipleInstance + component))
                        {
                            PerformanceCounterCategory.Delete(CategoryNameMultipleInstance + component);
                        }
                        PerformanceCounterCategory.Create(CategoryNameMultipleInstance + component, CategoryHelpMultipleInstance, PerformanceCounterCategoryType.MultiInstance, datas2);
                    }
                }
                if ((settings == PerformanceCounterLoadSetting.RegisterAndCreate) || (settings == PerformanceCounterLoadSetting.CreateOnly))
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        PerformanceCounter pc = new PerformanceCounter(CategoryName + component, list[i], false);
                        try
                        {
                            countersSingleInstance.Add(list[i], new ImPMPerformanceCounter(pc));
                        }
                        catch (ArgumentException)
                        {
                        }
                    }
                    for (int j = 0; j < list2.Count; j++)
                    {
                        List<string> list3;
                        dictionary.TryGetValue(list2[j], out list3);
                        foreach (string str in list3)
                        {
                            PerformanceCounter counter2 = new PerformanceCounter(CategoryNameMultipleInstance + component, list2[j], str, false);
                            counter2.RawValue = 0L;
                            KeyValuePair<string, string> key = new KeyValuePair<string, string>(list2[j], str);
                            try
                            {
                                countersMultipleInstance.Add(key, new ImPMPerformanceCounter(counter2));
                                continue;
                            }
                            catch (ArgumentException)
                            {
                                continue;
                            }
                        }
                    }
                }
            }
        }

        public static void LoadCounters(FileSystemInfo fileInfo, PerformanceCounterLoadSetting settings, string component)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(CounterContainer));
            using (XmlReader reader = XmlReader.Create(fileInfo.Name))
            {
                counterContainer = (CounterContainer)serializer.Deserialize(reader);
            }
            LoadCounters(counterContainer, settings, component);
        }

        public static void LoadCounters(string xml, PerformanceCounterLoadSetting settings, string component)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(CounterContainer));
            StreamReader textReader = new StreamReader(xml);
            counterContainer = (CounterContainer)serializer.Deserialize(textReader);
            textReader.Close();
            LoadCounters(counterContainer, settings, component);
        }

        public static void SerializeCounterInfo(string fileName)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(CounterContainer));
            XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.UTF8);
            writer.Formatting = Formatting.Indented;
            serializer.Serialize((XmlWriter)writer, counterContainer);
            writer.Close();
        }

        public static void SetValue(string counterName, long value)
        {
            ImPMPerformanceCounter counter;
            countersSingleInstance.TryGetValue(counterName, out counter);
            counter.PC.RawValue = value;
        }

        public static void SetValue(string counterName, string instanceName, long value)
        {
            ImPMPerformanceCounter counter;
            KeyValuePair<string, string> key = new KeyValuePair<string, string>(counterName, instanceName);
            countersMultipleInstance.TryGetValue(key, out counter);
            counter.PC.RawValue = value;
        }
    }


}
